export const getHeaders = (config: OpenAPIConfig, options: ApiRequestOptions): Observable<HttpHeaders> => {
	return forkJoin({
		token: resolve(options, config.TOKEN),
		username: resolve(options, config.USERNAME),
		password: resolve(options, config.PASSWORD),
		additionalHeaders: resolve(options, config.HEADERS),
	}).pipe(
		map(({ token, username, password, additionalHeaders }) => {
			const headers = Object.entries({
				Accept: 'application/json',
				...additionalHeaders,
				...options.headers,
			})
				.filter(([_, value]) => isDefined(value))
				.reduce((headers, [key, value]) => ({
					...headers,
					[key]: String(value),
				}), {} as Record<string, string>);

			if (isStringWithValue(token)) {
				headers['Authorization'] = `Bearer ${token}`;
			}

			if (isStringWithValue(username) && isStringWithValue(password)) {
				const credentials = base64(`${username}:${password}`);
				headers['Authorization'] = `Basic ${credentials}`;
			}

			if (options.body !== undefined) {
				if (options.mediaType) {
					headers['Content-Type'] = options.mediaType;
				} else if (isBlob(options.body)) {
					headers['Content-Type'] = options.body.type || 'application/octet-stream';
				} else if (isString(options.body)) {
					headers['Content-Type'] = 'text/plain';
				} else if (!isFormData(options.body)) {
					headers['Content-Type'] = 'application/json';
				}
			}

			return new HttpHeaders(headers);
		}),
	);
};
